package com.acme.bankapp.service.bank;

import java.util.List;

import com.acme.bankapp.domain.bank.*;
import com.acme.bankapp.domain.bank.exceptions.ClientAlreadyExistsException;
import com.acme.bankapp.domain.bank.exceptions.NotEnoughFundsException;

/**
 * @author Artem Kalchenko
 *
 */
public class BankService {

	/**
	 * Add a new client to a bank
	 * 
	 * @param bank
	 * @param client
	 * @return client
	 */

	public Client addClient(Bank bank, Client client) {
		try {
			bank.addClient(client);
			return client;
		} catch (ClientAlreadyExistsException e) {
			System.out.println("Client with same name and gender already exists");
			return null;
		}
	}

	/**
	 * Add a new client to a bank
	 * 
	 * @param bank
	 * @param name
	 * @param gender
	 * @return client object
	 */

	public Client addClient(Bank bank, String name, Gender gender) {
		Client client = new Client(name, gender);
		try {
			bank.addClient(client);
			return client;
		} catch (ClientAlreadyExistsException e) {
			System.out.println("Client with same name and gender already exists");
			return null;
		}
	}
	
	/**
	 * Get a client list
	 * 
	 * @param bank
	 * @param client
	 */

	public List<Client> getClientsList(Bank bank) {
		return bank.getClients();
	}
	/**
	 * Add an account to a given client
	 * 
	 * @param client
	 * @param account
	 */
	public void addAccount(Client client, Account account) {
		client.addAccount(account);
	}

	/**
	 * Report the list of bank's clients
	 * 
	 * @param bank
	 * @return list of client names on separate lines
	 */
	public String getClientsListAsString(Bank bank) {
		StringBuffer buff = new StringBuffer();

		for (Client cl : bank.getClients()) {
			buff.append(cl.getClientSalutation());
			buff.append("\n");
		}
		return buff.toString();
	}

	/**
	 * Report the state of client's accounts
	 * 
	 * @param bank
	 * @return list of client's accounts with balance on separate lines
	 */
	public String getClientAccount(Client client) {
		StringBuffer buff = new StringBuffer();

		for (Account acc : client.getAccounts()) {
			buff.append(acc.toString() + ": ");
			buff.append(acc.getBalance());
			buff.append("\n");
		}
		return buff.toString();
	}

	/**
	 * Report the list of bank's accounts
	 * 
	 * @param bank
	 * @return list of client names with their accounts on separate lines
	 */
	public String getAccountsListAsString(Bank bank) {
		StringBuffer buff = new StringBuffer();

		for (Client cl : bank.getClients()) {
			buff.append(cl.getClientSalutation());
			buff.append(":\n");
			for (Account acc : cl.getAccounts()) {
				buff.append("\t" + acc.toString() + ":\n");
				buff.append("\t Balance " + acc.getBalance());
				buff.append("\t Max withdraw " + acc.maximumAmountToWithdraw());
				buff.append("\n");
			}
		}
		return buff.toString();
	}

	/**
	 * Withdraw money from client's account
	 * 
	 * @param client
	 * @param amount
	 * @return true if money successfully withdrawn, false if not enough money
	 */
	public void withdraw(Client client, double amount) {
		try {
			client.getAccount().withdraw(amount);
		} catch (NotEnoughFundsException e) {
			System.out.println("The balance is insufficient to withdraw " + amount);
		} catch (IllegalArgumentException e) {
			System.out.println("Withdraw amount is illegal");
		}
	}
	
	/**
	 * Deposit money on client's account
	 * 
	 * @param client
	 * @param amount
	 */
	public void deposit(Client client, double amount) {
		client.getAccount().deposit(amount);
	}
	
	/**
	 * Set an overdraft limit for the client's checking account
	 * 
	 * @param client
	 * @param overdraftLim - limit
	 */
	public boolean setOverdraftLimit(Client client, double overdraftLim) {
		if (client.getAccount() instanceof CheckingAccount){
			((CheckingAccount)client.getAccount()).setMaxOverdraft(overdraftLim);
			return true;
		}
		return false;
	}
	
}
